package com.googlecode.continuity.core.client;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.io.Serializable;

import com.google.gwt.user.client.rpc.IsSerializable;

/**
 * The User represents the standard implementation of the {@link com.googlecode.continuity.core.client.ContinuityUser}
 * interface, providing user information (name, email, registered, etc.) and basic authorization through the authority
 * system (see also {@link GrantedAuthority}).
 *
 * @author Peter Schmitt <aragos@aragos.de>
 */
public class User implements ContinuityUser, IsSerializable, Serializable {
// ------------------------------ FIELDS ------------------------------

  private int id;
  private String username;
  private String email;
  private Date registered;
  private Date lastSeen;

  /**
   * @gwt.typeArgs <com.googlecode.continuity.core.client.GrantedAuthority>
   */
  private Set authorities;

// --------------------- GETTER / SETTER METHODS ---------------------

  /**
   * Returns a set of this user's authority tokens.
   *
   * @return set of authorities
   */
  public Set getAuthorities() {
    if (authorities == null) {
      authorities = new HashSet();
    }
    return authorities;
  }

  /**
   * Returns this user's email address.
   *
   * @return email address
   */
  public String getEmail() {
    return email;
  }

  /**
   * Sets a new email address for this user.
   *
   * @param email new email address
   */
  public void setEmail(String email) {
    this.email = email;
  }

  /**
   * Returns this user's unique id.
   *
   * @return user id
   */
  public int getId() {
    return id;
  }

  /**
   * Returns the date and time at which this user last logged into the system.
   *
   * @return last login date and time
   */
  public Date getLastSeen() {
    return lastSeen;
  }

  /**
   * Sets the date and time of this user's most recent login.
   *
   * @param lastSeen date and time for this user's most recent login
   */
  public void setLastSeen(Date lastSeen) {
    this.lastSeen = lastSeen;
  }

  /**
   * Returns the date and time on which this user registered with the system.
   *
   * @return the date and time on which this user registered with the system
   */
  public Date getRegistered() {
    return registered;
  }

  /**
   * Sets the date and time of this user's registration.
   *
   * @param registered date and time of this user's registration
   */
  public void setRegistered(Date registered) {
    this.registered = registered;
  }

  /**
   * Returns this user's name.
   *
   * @return this user's name
   */
  public String getUsername() {
    return username;
  }

  /**
   * Sets a new name for this user.
   *
   * todo: remove?
   *
   * @param username new name
   */
  public void setUsername(String username) {
    this.username = username;
  }

// ------------------------ INTERFACE METHODS ------------------------

// --------------------- Interface ContinuityUser ---------------------

  /**
   * Returns <code>true</code> if this user has been granted the authority described by the role description.
   *
   * @param roleDescription string-ified description of this the authority
   * @return <code>true</code> if this user has been granted the authority described by the given description
   * @see com.googlecode.continuity.core.client.GrantedAuthority
   */
  public boolean hasAuthority(String roleDescription) {
    Iterator it = authorities.iterator();
    while (it.hasNext()) {
      if (("ROLE_" + ((GrantedAuthority) it.next()).getName().toUpperCase()).equals(roleDescription)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Grants an authority to this user by adding it to the user's set of authorities.
   *
   * @param authority newly granted authority
   */
  public void grantAuthority(GrantedAuthority authority) {
    getAuthorities().add(authority);
  }

  /**
   * Revokes an authority from this user by removing it from the user's set of authorities.
   *
   * @param authority authority to be revoked
   */
  public void revokeAuthority(GrantedAuthority authority) {
    getAuthorities().remove(authority);
  }

// -------------------------- OTHER METHODS --------------------------

  /**
   * Performs an equality check of user objects using their unique id.
   *
   * @param otherUser user to be compared
   * @return true if users have the same id, false otherwise
   */
  public boolean equals(Object otherUser) {
    if (this == otherUser) {
      return true;
    }
    if (!(otherUser instanceof User)) {
      return false;
    }

    User user = (User) otherUser;

    return id == user.id;

  }

  /**
   * Returns a hashcode using this user's unique id.
   *
   * @return hashcode generated from user's id
   */
  public int hashCode() {
    return id;
  }
}
